#!/user/bin/even Python3
# -*- coding:utf-8 -*-
# RunByUiYmal.py
# 执行Ymal文件的UI
# author:zhaohexin
# time：2020/5/22 15:58
# include <QTextCursor>

import ctypes
import os
import platform
import sys
import time

from PyQt5.QtCore import QThread, pyqtSignal, Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox, QTreeWidgetItem
import subprocess

from ASetOfTables import Ui_ASetOfTables

from myuntils.GuiDataYmal import data_acquisition
from myuntils.GuiDataYmal import data_store

os.environ["CUDA_VISIBLE_DEVICES"] = "-1"


class message(QThread):
    signal = pyqtSignal()

    def __init__(self, Window, obj):
        super(message, self).__init__()
        self.window = Window
        self.obj = obj

    def run(self):
        get_log(self.obj)
        self.signal.emit()


def check_dir_line1():
    """
    实现选择文件夹后向相应的LineEdit赋值
    :param LineEdit:
    :return:
    """
    dir = QFileDialog.getOpenFileName()
    myWin.lineEdit.setText(dir[0])


def check_dir_line6():
    """
    实现选择文件夹后向相应的LineEdit赋值
    :param LineEdit:
    :return:
    """
    dir = QFileDialog.getExistingDirectory()
    myWin.lineEdit_6.setText(dir)


def check_dir_line7():
    """
    实现选择文件夹后向相应的LineEdit赋值
    :param LineEdit:
    :return:
    """
    dir = QFileDialog.getExistingDirectory()
    myWin.lineEdit_7.setText(dir)


def check_dir_line8():
    """
    实现选择文件夹后向相应的LineEdit赋值
    :param LineEdit:
    :return:
    """
    dir = QFileDialog.getExistingDirectory()
    myWin.lineEdit_8.setText(dir)
    # 将系统选择重置为全部
    myWin.comboBox_2.setCurrentText("全部")
    # 重新获取data数据
    myWin.data = data_acquisition(dir)
    # 刷新下方功能/用例模块数据
    check_system()

def click_radioButton():
    """
    点击设置尺寸时触发逻辑
    :return: 
    """
    if browser_sizes_3.isChecked() is False:
        myWin.lineEdit_4.setText("")
        myWin.lineEdit_5.setText("")
        myWin.lineEdit_4.setEnabled(False)
        myWin.lineEdit_5.setEnabled(False)
    else:
        myWin.lineEdit_4.setEnabled(True)
        myWin.lineEdit_5.setEnabled(True)


def check_system():
    """
    切换系统时刷新下方树
    :return:
    """

    check_ = commbox_system.currentText()
    i = 0
    if check_ == "全部":
        modules = myWin.data["all_module"]
    elif check_ == "统计端":
        modules = myWin.data["businessid_module"]
    elif check_ == "企业端":
        modules = myWin.data["statisticsend_module"]
    else:
        modules = []
    three.clear()
    for module in modules:
        # 添加父节点
        item = QTreeWidgetItem(myWin.treeWidget)
        item.setCheckState(0, 0)
        item.setFlags(
            Qt.ItemIsSelectable | Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsTristate)
        myWin.treeWidget.topLevelItem(i).setText(0, module)
        # 添加子节点
        k = 0
        for case in myWin.data["all_cases"][module]:
            item_1 = QTreeWidgetItem(item)
            item_1.setCheckState(0, 0)
            myWin.treeWidget.topLevelItem(i).child(k).setText(0, case)
            k += 1
        i += 1
    return i


def begin_case():
    """
    开始执行用例
    :return:
    """
    # 判断是否在进程中
    if not myWin.pid:
        # 获取当前页面数据
        ini_data = get_windos_data()
        # 获取进程
        is_root_password = True
        if myWin.system == "Linux" and myWin.lineEdit_9.text() == "":
            is_root_password = False
        if is_root_password:
            check = os.popen(f"echo {myWin.lineEdit_9.text()}|sudo -S ls").read() != ""
            if check or myWin.system == "Windows":
                # 判断是否存在用例
                if ini_data["count"] != 0:
                    # 存储到用例配置
                    data_store(ini_data)
                    # 开始执行用例
                    try:
                        base_path = sys._MEIPASS
                    except Exception as e:
                        base_path = os.path.abspath(".")
                    if myWin.system == 'Windows':
                        cmd = os.path.join(base_path, 'StartUpYmal', 'RunYmal.exe')
                        p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                             bufsize=-1)
                    elif myWin.system == "Linux":

                        cmd = f"{os.path.join(base_path, 'StartUpYmal', 'RunYmal')}"
                        p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                             bufsize=-1)
                    myWin.pid = p.pid
                    myWin.sub = p
                    # 进行日志循环输出
                    myWin.textBrowser.setText("日志输出")
                    myWin.textBrowser.append("----------程序启动中，请稍后----------")
                    myWin.my_thread = message(myWin, p)  # 步骤2. 主线程连接子线
                    try:
                        myWin.my_thread.signal.connect(myWin.finsh_case)  # 自定义信号连接
                        myWin.my_thread.start()  # 步骤3 子线程开始执行run函数
                    except:
                        pass
                else:
                    myWin.slotAbout()
            else:
                myWin.check_password()
        else:
            myWin.password()
    else:
        myWin.IsUsePid()


def get_log(obj):
    """
    循环打印日志
    :param obj:
    :return:
    """
    if myWin.system == "Windows":
        encoding = "gbk"
    elif myWin.system == "Linux":
        encoding = "utf-8"
    while True:
        line = str(obj.stdout.readline(), encoding=encoding)
        if line == '' or line is None:
            myWin.pid = ""
            break
        else:
            print(line)
            myWin.textBrowser.append(line)
            myWin.textBrowser.moveCursor(myWin.textBrowser.textCursor().End)
            time.sleep(0.001)


def close_windows():
    """
    关闭窗口
    :return:
    """
    myWin.close()


def check_browser_select():
    """
    选择浏览器操作
    """
    if myWin.comboBox.currentText() == "360安全浏览器":
        myWin.label_21.show()
        myWin.lineEdit_10.show()
        if myWin.lineEdit_10.text() == "" and platform.system() == "Linux":
            myWin.lineEdit_10.setText("/usr/bin/browser360-cn")
    else:
        myWin.label_21.hide()
        myWin.lineEdit_10.hide()


def get_windos_data():
    """
    获取当前页面所有数据
    :return:
    """
    # 选择浏览器
    broswer = myWin.comboBox.currentText()
    # 浏览器启动路径
    broswer_path = myWin.lineEdit_10.text()
    # 浏览器插件路径
    broswer_plugin_path = myWin.lineEdit.text() if myWin.lineEdit.text() != "默认当前目录下存储" else ""
    # 统计端登录地址
    businesside_url = myWin.lineEdit_2.text()
    # 企业端登录地址
    thestatisticsend_url = myWin.lineEdit_3.text()
    # 浏览器尺寸
    if myWin.radioButton.isChecked() is True:
        browser_size = ""
    elif myWin.radioButton_2.isChecked() is True:
        browser_size = ["800", "600"]
    else:
        browser_size = [myWin.lineEdit_4.text(), myWin.lineEdit_5.text()]
    # 报告错误截图存储路径
    report_image_path = myWin.lineEdit_6.text() if myWin.lineEdit_6.text() != "默认当前目录下存储" else ""
    # 报告文件存储位置
    report_file_path = myWin.lineEdit_7.text() if myWin.lineEdit_7.text() != "默认当前目录下存储" else ""
    # 报告用例存储位置
    case_file_path = myWin.lineEdit_8.text() if myWin.lineEdit_8.text() != "默认当前目录下存储" else ""
    # 执行系统选择
    excution_system = myWin.comboBox_2.currentText()
    # 执行模块及系统选择
    excution_module = []
    excution_cases = {}
    count = three.topLevelItemCount()
    for i in range(count):
        item = three.topLevelItem(i)
        # 选中状态
        if item.checkState(0) == 0:
            pass
        else:
            # 获取名称
            excution_module.append(item.text(0))
            excution_cases[item.text(0)] = []
        # 获取子项
        childCount = item.childCount()
        for k in range(childCount):
            if three.topLevelItem(i).child(k).checkState(0) == 0:
                pass
            else:
                excution_cases[item.text(0)].append(three.topLevelItem(i).child(k).text(0))
    # root用户密码
    root_password = myWin.lineEdit_9.text()
    myWin.root_password = root_password

    return {"run_browser": broswer,
            "run_browser_path": broswer_path,
            "customize_plugin_path": broswer_plugin_path,
            "businesside_url": businesside_url,
            "thestatisticsend_url": thestatisticsend_url,
            "browser_size": browser_size,
            "report_image_path": report_image_path,
            "report_file_path": report_file_path,
            "case_file_path": case_file_path,
            "excution_system": excution_system,
            "excution_module": excution_module,
            "excution_cases": excution_cases,
            "count": count,
            "root_password": root_password
            }


class MyWindow(QMainWindow, Ui_ASetOfTables):
    def __init__(self, parent=None):
        self.data = data_acquisition()
        super(MyWindow, self).__init__(parent)
        self.setupUi(self, self.data)
        self.pid = ""
        self.system = platform.system()

    def slotAbout(self):
        QMessageBox.about(self, "警告", self.tr("当前无可执行模块，请重新检查用例路径是否正确！"))

    def IsUsePid(self):
        QMessageBox.about(self, "警告", self.tr("当前正在执行用例测试，请勿重复点击！"))

    def finsh_case(self):

        QMessageBox.information(self, "提示", f"用例执行完成，请于所配置目录下查看报告及错误截图。",
                                QMessageBox.Yes)

    def password(self):
        QMessageBox.about(self, "警告", self.tr("当前系统为Linux，请输入root密码！"))

    def check_password(self):
        QMessageBox.about(self, "警告", self.tr("用户密码不正确，请重新输入！"))

    def closeEvent(self, event):
        print(self.pid)
        reply = QMessageBox.warning(self, '警告', '退出后测试将停止,\n你确认要退出吗？',
                                    QMessageBox.Yes, QMessageBox.No)
        if reply == QMessageBox.Yes:
            try:
                if self.system == "Windows":
                    os.system(f"taskkill /pid {self.pid}  -t  -f")
                elif self.system == "Linux":
                    self.sub.terminate()
                    os.system(f"echo {self.root_password}|sudo -S rm -rf /tmp/_*")
            except Exception as e:
                pass
            event.accept()
        else:
            event.ignore()


try:
    system = platform.system()
    if system == 'Windows':
        whnd = ctypes.windll.kernel32.GetConsoleWindow()
        if whnd != 0:
            ctypes.windll.user32.ShowWindow(whnd, 0)
    app = QApplication(sys.argv)
    myWin = MyWindow()
    myWin.show()

    # 选择浏览器，解放配置
    browser_select = myWin.comboBox
    browser_select.currentIndexChanged.connect(check_browser_select)
    # 实现选择目录功能
    # 选择自定义浏览器插件
    browser_plug_btn = myWin.pushButton
    browser_plug_btn.clicked.connect(check_dir_line1)
    # 选择错误截图存储位置
    img_btn = myWin.pushButton_2
    img_btn.clicked.connect(check_dir_line6)
    # 报告文件存储位置
    report_btn = myWin.pushButton_3
    report_btn.clicked.connect(check_dir_line7)
    # 判断是否为自定义，若为非自定义尺寸，锁长宽格子
    browser_sizes = myWin.radioButton
    browser_sizes.clicked.connect(click_radioButton)
    browser_sizes_2 = myWin.radioButton_2
    browser_sizes_2.clicked.connect(click_radioButton)
    browser_sizes_3 = myWin.radioButton_3
    browser_sizes_3.clicked.connect(click_radioButton)
    # 选择树时逻辑
    three = myWin.treeWidget
    # 选中执行系统切换下方用例
    commbox_system = myWin.comboBox_2
    commbox_system.currentIndexChanged.connect(check_system)
    # 点击开始用例按钮，执行程序
    begin_case_btn = myWin.pushButton_4
    begin_case_btn.clicked.connect(begin_case)
    # 点击关闭按钮，关闭程序
    close_btn = myWin.pushButton_5
    close_btn.clicked.connect(close_windows)
    # 用例文件存储路径
    case_btn = myWin.pushButton_6
    case_btn.clicked.connect(check_dir_line8)

    sys.exit(app.exec_())
except Exception as e:
    with open(os.path.join(os.path.abspath("."), "log.txt"), "a", encoding="utf-8") as f:
        f.write(f"\n{e}")
